package com.sojson.config.mybatis.interceptor;

import java.util.List;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.sojson.config.mybatis.interceptor.bean.CustomTenantLineHandler;

import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;

/**
 * Mybatis租户拦截器
 * 
 * @author liu
 * @date 2022-01-20
 */
// @Component
public class CustomTenantLineInnerInterceptor extends TenantLineInnerInterceptor {

    public CustomTenantLineInnerInterceptor() {
        this(new CustomTenantLineHandler());
    }

    public CustomTenantLineInnerInterceptor(TenantLineHandler tenantLineHandler) {
        super(tenantLineHandler);
    }

    @Override
    protected void processInsert(Insert insert, int index, String sql, Object obj) {
        TenantLineHandler handler = getTenantLineHandler();

        // 如果忽略这张表就结束
        if (handler.ignoreTable(insert.getTable().getName())) {
            return;
        }

        List<Column> columns = insert.getColumns();
        // 如果语句没有字段就结束
        if (CollectionUtils.isEmpty(columns)) {
            return;
        }

        String tenantIdColumn = handler.getTenantIdColumn();
        // 如果语句中已经有了租户条件就结束
        if (columns.stream().map(Column::getColumnName).anyMatch(i -> i.equalsIgnoreCase(tenantIdColumn))) {
            return;
        }

        // 添加租户字段
        columns.add(new Column(tenantIdColumn));

        Select select = insert.getSelect();
        if (select != null) {
            this.processInsertSelect(select.getSelectBody());
        } else if (insert.getItemsList() != null) {
            ItemsList itemsList = insert.getItemsList();
            if (itemsList instanceof MultiExpressionList) {
                ((MultiExpressionList)itemsList).getExpressionLists()
                    .forEach(el -> el.getExpressions().add(handler.getTenantId()));
            } else {
                ((ExpressionList)itemsList).getExpressions().add(handler.getTenantId());
            }
        } else {
            throw ExceptionUtils
                .mpe("Failed to process multiple-table update, please exclude the tableName or statementId");
        }
    }

}